<?php

namespace app\data\controller\api\auth;

use app\data\controller\api\Auth;
use app\data\service\BaseUserMessageService;
use app\data\service\OrderService;
use app\data\service\UserAdminService;
use app\data\service\UserBalanceService;
use think\admin\extend\CodeExtend;

/**
 * 服务商订单数据接口
 * Class Order
 * @package app\data\controller\api\auth
 */
class ServiceProviderOrder extends Auth
{
    /**
     * 控制器初始化
     */
    protected function initialize()
    {
        parent::initialize();
        if (empty($this->user['status'])) {
            $this->error('账户已被冻结，不能操作订单数据哦！');
        }
    }

    /**
     * 查看进度列表
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function get()
    {
        $data = $this->_vali([
            'plate_number.default' => '',
            'status.default' => '',
        ]);

        $query = $this->_query('car_order_review')
            ->where('service_provider_uid', $this->uuid);

        if (!empty($data['plate_number'])) {
            $query->where('plate_number', 'like', "%{$data['plate_number']}%");
        }
        if ($data['status'] !== '') {

            if ($data['status'] == '4') {
                $query->whereIn('status', [3, 4]);
            } else if ($data['status'] == '1') {
                $query->whereIn('status', [1, 2, 3, 4]);
            } else if ($data['status'] == '5') {
                $query->whereIn('status', [5, 6]);
            } else {
                $query->where('status', $data['status']);
            }
        }

        $result = $query->field('id,status,order_no,plate_number,snapshot,pay_at')
            ->order('pay_at desc, id desc')->page(true, false, false, 20);
        foreach ($result['list'] as &$vo) {
            $snapshot = json_decode($vo['snapshot'], true);
            $vo['vehicle_type'] = $snapshot['car_info']['vehicle_type'] ?? [];
            if (empty($snapshot['car_info']['car_conditions'] ?? '')) {
                $vo['car_conditions'] = [];
            } else {
                $vo['car_conditions'] = explode('、', $snapshot['car_info']['car_conditions'] ?? '');
            }

            $vo['status_text'] = OrderService::instance()->orderReviewStatus2Text($vo['status']);
            $vo['pay_at'] = date('Y-m-d H:i', strtotime($vo['pay_at']));
            unset($vo['snapshot']);
        }
        $this->success('获取进度列表数据成功！', $result);
    }

    /**
     * 接单列表
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function receivingList()
    {
        $orderBases = $this->app->db->name('car_order_base')
            ->where('status', 1)
            ->where('province', $this->user['region_province'] ?? '')
            ->where('city', $this->user['region_city'] ?? '')
            ->select()
            ->toArray();
        $orderReviewIds = array_column($orderBases, 'order_review_id');

        $result = $this->_query('car_order_review')
            ->where('status', 0)
            ->where('service_provider_uid', 0)
            ->whereIn('id', $orderReviewIds)
            ->field('id,status,order_no,plate_number,snapshot,pay_at')
            ->order('pay_at desc, id desc')
            ->page(true, false, false, 20);

        foreach ($result['list'] as &$vo) {
            $snapshot = json_decode($vo['snapshot'], true);
            $vo['vehicle_type'] = $snapshot['car_info']['vehicle_type'] ?? [];

            if (empty($snapshot['car_info']['car_conditions'] ?? '')) {
                $vo['car_conditions'] = [];
            } else {
                $vo['car_conditions'] = explode('、', $snapshot['car_info']['car_conditions'] ?? '');
            }
            $vo['status_text'] = OrderService::instance()->orderReviewStatus2Text($vo['status']);
            $vo['pay_at'] = date('Y-m-d H:i', strtotime($vo['pay_at']));
            unset($vo['snapshot']);
        }
        $this->success('获取订单数据成功！', $result);
    }

    /**
     * 接单详情
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function receivingDetail()
    {
        $data = $this->_vali([
            'order_no.require' => '订单号不能为空',
        ]);

        $order = $this->app->db->name('car_order_review')
            ->where('order_no', $data['order_no'])
            ->field('id,status,order_no,plate_number,snapshot,pay_at,hope_review_at')
            ->findOrEmpty();

        // 关联基础订单
        $carOrderBase = $this->app->db->name('car_order_base')
            ->where('order_review_id', $order['id'])
            ->findOrEmpty();

        if (empty($order) || empty($carOrderBase)) {
            $this->error('查无该接单详情');
        }

        $snapshot = json_decode($order['snapshot'], true);
        $order['car_info'] = $snapshot['car_info'] ?? [];
        if (!empty($order['car_info'])) {

            if (empty($order['car_info']['car_conditions'] ?? '')) {
                $order['car_info']['car_conditions'] = [];
            } else {
                $order['car_info']['car_conditions'] = explode('、', $order['car_info']['car_conditions'] ?? '');
            }
        }
        $order['car_info']['phone'] = hiddenPhone($order['car_info']['phone']);

        $order['hope_review_at'] = date('Y-m-d', strtotime($order['hope_review_at']));
        $order['address_detail'] = $carOrderBase['province'] . $carOrderBase['city'] . $carOrderBase['area'];
        $order['status_text'] = OrderService::instance()->orderReviewStatus2Text($order['status']);
        unset($order['snapshot']);

        $this->success('获取订单数据成功！', $order);
    }

    /**
     * 服务商接单
     * @return void
     */
    public function receiving()
    {
        $data = $this->_vali([
            'order_no.require' => '订单号不能为空'
        ]);

        $order = $this->app->db->name('car_order_review')
            ->where('order_no', $data['order_no'])
            ->findOrEmpty();

        if ($order['status'] !== 0 || $order['service_provider_uid']) {
            $this->error('该订单已经被接单了');
        }

        try {
            // 写入订单数据
            $receivedAt = date('Y-m-d H:i:s');
            $this->app->db->transaction(function () use ($order, $receivedAt) {
                $this->app->db->name('car_order_review')->where('id', $order['id'])->update(['status' => 1, 'received_at' => $receivedAt, 'service_provider_uid' => $this->uuid, 'update_at' => $receivedAt]);
                $this->app->db->name('car_order_base')->where('order_review_id', $order['id'])->update(['status' => 1, 'service_provider_uid' => $this->uuid]);
            });
        } catch (\Exception $exception) {
            $this->error("接单单失败，{$exception->getMessage()}");
        }

        $isReceived = $this->app->db->name('car_order_review')
            ->where('order_no', $order['order_no'])
            ->where('service_provider_uid', $this->uuid)
            ->findOrEmpty();

        if (!$isReceived) {
            $this->error('接单失败');
        }

        // 消息通知
        $message = [
            '已接单',
            $order['order_no'],
            $receivedAt,
            "【订单已接单】您提交的年审订单{$order['order_no']}已接单，请与对应服务商联系"
        ];
        BaseUserMessageService::instance()->sendMessage($order['uuid'], '已接单', $message);

        $this->success('接单成功');
    }

    /**
     * 服务商今日接单数
     * @return void
     */
    public function receivingTodayCount()
    {
        $count = $this->app->db->name('car_order_review')
            ->where('service_provider_uid', $this->uuid)
            ->where('status', '>=', 1)
            ->whereBetweenTime('received_at', date('Y-m-d') . "00:00:00", date('Y-m-d H:i:s'))
            ->count();

        $this->success('服务商今日接单数', ['count' => $count]);
    }

    /**
     * 订单详情
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function detail()
    {
        [$map, $order] = $this->getOrderData();

        // 关联基础订单
        $carOrderBase = $this->app->db->name('car_order_base')
            ->withoutField('id,order_review_id,uuid,service_provider_uid,car_info_id,order_no,snapshot')
            ->where('order_review_id', $order['id'])
            ->findOrEmpty();

        // 关联加价订单
        $carOrderAdd = $this->app->db->name('car_order_add')
            ->withoutField('id,order_review_id,uuid,service_provider_uid,car_info_id,order_no,snapshot')
            ->where('order_review_id', $order['id'])
            ->findOrEmpty();
        if (!empty($carOrderAdd)) {
            $carOrderAdd['add_info'] = json_decode($carOrderAdd['add_info'], true);
        }

        // 关联司机信息
        $user = [
            'id' => $this->user['id'],
            'phone' => $this->user['phone'],
            'nickname' => $this->user['nickname'],
            'headimg' => $this->user['headimg'],
        ];
        $user = UserAdminService::instance()->formatUserField($user, false);

        // 关联服务商信息
        $serviceProvider = $this->app->db->name('DataUser')
            ->field('id,phone,nickname,headimg')
            ->where('id', $order['service_provider_uid'])
            ->findOrEmpty();
        $serviceProvider = UserAdminService::instance()->formatUserField($serviceProvider, false);

        $order['order_base'] = $carOrderBase ?: null;
        $order['order_add'] = $carOrderAdd ?: null;
        $order['user'] = $user ?: null;
        $order['service_provider'] = $serviceProvider ?: null;
        $order['status_text'] = OrderService::instance()->orderReviewStatus2Text($order['status']);
        $order['order_base_status_text'] = OrderService::instance()->orderBaseStatus2Text($carOrderBase['status'] ?? '');
        $order['order_add_status_text'] = OrderService::instance()->orderAddStatus2Text($carOrderAdd['status'] ?? '');
        $order['snapshot'] = json_decode($order['snapshot'], true);
        if (!empty($order['snapshot']['car_info'])) {
            $order['snapshot']['car_info']['car_conditions'] = explode('、', $order['snapshot']['car_info']['car_conditions']);
            $order['snapshot']['car_info']['appearances'] = json_decode($order['snapshot']['car_info']['appearances'] ?: '[]', true);
        }
        if (empty($order['snapshot']['car_monitoring_station_plan'])) {
            $order['snapshot']['car_monitoring_station_plan'] = $this->app->db->table('car_monitoring_station')->where('id', $order['car_monitoring_station_id_plan'])->findOrEmpty();
        }

        $this->success('获取订单数据成功！', $order);
    }

    /**
     * 预约线下审车
     * @return void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function planOffline()
    {
        [$map, $order] = $this->getOrderData();

        $data = $this->_vali([
            'plan_offline_at.require' => '预约线下审车日期不能为空',
            'car_monitoring_station_id_offline.value' => $order['car_monitoring_station_id_offline']
        ]);

        if (empty($order)) {
            $this->error('查无该接单详情');
        }

        if ($order['status'] !== 1) {
            $this->error('已经预约线下审车了');
        }

        $carMonitoringStation = $this->app->db->table('car_monitoring_station')->where('id', $order['car_monitoring_station_id_offline'])->where('status', 1)->findOrEmpty();
        if (empty($carMonitoringStation)) {
            $this->error('查无该检测站');
        }
        $carMonitoringStation['price'] = $this->app->db->table('car_monitoring_station_price')->where('car_monitoring_station_id', $order['car_monitoring_station_id_offline'])->findOrEmpty()['price'] ?? 0;

        $snapshot = json_decode($order['snapshot'], true);
        $snapshot['car_monitoring_station_offline'] = $carMonitoringStation;

        $result = $this->app->db->name('car_order_review')->where('id', $order['id'])->update([
            'status' => 2,
            'car_monitoring_station_id_offline' => $data['car_monitoring_station_id_offline'],
            'plan_offline_at' => date('Y-m-d H:i:s', strtotime($data['plan_offline_at'])),
            'snapshot' => json_encode($snapshot),
            'update_at' => date('Y-m-d H:i:s'),
        ]);

        if (!$result) {
            $this->error('预约线下审车失败');
        }

        // 消息通知
        $message = [
            '预约线下审车',
            $this->user['nickname'],
            '暂无',
            '等待线下审车',
            "【预约线下审车】您提交的年审订单{$order['order_no']}，服务商已发起预约线下审车，请注意查看"
        ];
        BaseUserMessageService::instance()->sendMessage($order['uuid'], '预约线下审车', $message);

        $this->success('预约线下审车成功');
    }

    /**
     * 费用协商
     * @return void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function consultAddPrice()
    {
        [$map, $order] = $this->getOrderData();

        $data = $this->_vali([
            'add_info.require' => '增加费用项数组不能为空',
        ]);

        $orderAdd['price'] = 0;
        foreach ($data['add_info'] as $addInfo) {
            if (empty($addInfo['name'])) {
                $this->error('增加费用项不能为空');
            }
            if (empty($addInfo['price']) || $addInfo['price'] < 0) {
                $this->error('增加费用项不能为空');
            }
            $orderAdd['price'] += $addInfo['price'];
        }

        if (empty($order)) {
            $this->error('查无该接单详情');
        }

        if ($order['status'] !== 1) {
            $this->error('该状态无法进行费用协商了');
        }

        $snapshot = json_decode($order['snapshot'], true);

        // 年审订单数据
        $orderAdd['order_review_id'] = $order['id'];
        $orderAdd['status'] = 0;
        $orderAdd['uuid'] = $order['uuid'];
        $orderAdd['service_provider_uid'] = $order['service_provider_uid'];
        $orderAdd['car_info_id'] = $order['car_info_id'];
        $orderAdd['order_no'] = CodeExtend::uniqidDate(18, 'A');
        $orderAdd['snapshot'] = json_encode($snapshot);
        $orderAdd['add_info'] = json_encode($data['add_info']);

        try {
            // 写入订单数据
            $updateTime = date('Y-m-d H:i:s');
            $this->app->db->transaction(function () use ($order, $data, $orderAdd, $snapshot, $updateTime) {

                $this->app->db->name('car_order_review')->where('id', $order['id'])->update([
                    'status' => 3,
                    'snapshot' => json_encode($snapshot),
                    'consult_at' => $updateTime,
                    'update_at' => $updateTime,
                ]);

                $this->app->db->name('car_order_add')->insert($orderAdd);
            });
        } catch (\Exception $exception) {
            $this->error("生成增加费用订单失败，{$exception->getMessage()}");
        }

        // 消息通知
        $message = [
            '费用协商',
            '费用协商中',
            $updateTime,
            '',
            "【增加费用协商】您提交的年审订单{$order['order_no']}，服务商已提交费用协商，请注意查看"
        ];
        BaseUserMessageService::instance()->sendMessage($order['uuid'], '费用协商', $message);

        $this->success('生成增加费用订单成功');
    }

    /**
     * 安排年审
     * @return void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function planReview()
    {
        [$map, $order] = $this->getOrderData();

        $data = $this->_vali([
            'plan_review_at.default' => '预约年审审车时间不能为空',
            'car_monitoring_station_id_plan.default' => $order['car_monitoring_station_id_plan']
        ]);

        if (empty($order)) {
            $this->error('查无该接单详情');
        }

        if ($order['status'] !== 2 && $order['status'] !== 3) {
            $this->error('已经安排年审了');
        }

        $carMonitoringStation = $this->app->db->table('car_monitoring_station')->where('id', $order['car_monitoring_station_id_plan'])->where('status', 1)->findOrEmpty();
        if (empty($carMonitoringStation)) {
            $this->error('查无该检测站');
        }
        $carMonitoringStation['price'] = $this->app->db->table('car_monitoring_station_price')->where('car_monitoring_station_id', $order['car_monitoring_station_id_plan'])->findOrEmpty()['price'] ?? '';

        $snapshot = json_decode($order['snapshot'], true);
        $snapshot['car_monitoring_station_plan'] = $carMonitoringStation;

        // 费用协商情况下， 需要检查订单是否已经支付
        if ($order['status'] === 3) {
            $carOrderAdd = $this->app->db->name('car_order_add')->where('order_review_id', $order['id'])->where('status', 1)->findOrEmpty();
            if (!$carOrderAdd) {
                $this->error('增加费用订单尚未支付，无法安排年审');
            }
            $data['car_monitoring_station_id_plan'] = $carOrderAdd['car_monitoring_station_id_plan'];
        }

        $result = $this->app->db->name('car_order_review')->where('id', $order['id'])->update([
            'status' => 4,
            'car_monitoring_station_id_plan' => $data['car_monitoring_station_id_plan'],
            'plan_review_at' => date('Y-m-d H:i:s', strtotime($data['plan_review_at'])),
            'update_at' => date('Y-m-d H:i:s'),
            'snapshot' => json_encode($snapshot),
        ]);

        if (!$result) {
            $this->error('安排年审失败');
        }

        // 消息通知
        $message = [
            '安排年审',
            $this->user['nickname'],
            '暂无',
            date('Y-m-d H:i:s'),
            "【安排年审】您提交的年审订单{$order['order_no']}，服务商已安排年审，请注意查看"
        ];
        BaseUserMessageService::instance()->sendMessage($order['uuid'], '安排年审', $message);

        $this->success('安排年审成功');
    }

    /**
     * 年审完成
     * @return void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function complete()
    {
        [$map, $order] = $this->getOrderData();

        $data = $this->_vali([
            'driving_image_1.default' => '',
            'end_1.default' => '',
            'end_2.default' => '',
            'plate_number.default' => '',
        ]);

        if (empty($order)) {
            $this->error('查无该接单详情');
        }

//        if ($order['plate_number'] != $data['plate_number']) {
//            $this->error('当前车牌号码与订单不一致，不能提交');
//        }

        if (!in_array($order['status'], [1, 3])) {
            $this->error('该订单状态无法设置为年审完成');
        }

        $now = date('Y-m-d H:i:s');
        $result = $this->app->db->name('car_order_review')->where('id', $order['id'])->update([
            'status' => 6,
            'driving_image_1' => $data['driving_image_1'],
            'end_1' => $data['end_1'],
            'end_2' => $data['end_2'],
            'complete_at' => $now,
            'confirm_at' => $now,
            'update_at' => $now,
        ]);

        if (!$result) {
            $this->error('操作年审完成失败');
        }

        // 消息通知
        $message = [
            '年审完成',
            $order['plate_number'],
            $now,
            "【年审完成】您提交的年审订单{$order['order_no']}，服务商已提交年审完成，请注意查看"
        ];
        BaseUserMessageService::instance()->sendMessage($order['uuid'], '年审完成', $message);

        $snapshot = json_decode($order['snapshot'], true);
        $reviewPrice = $snapshot['car_monitoring_station_price']['review_price'];
        if (!empty($reviewPrice)) {
            $data['name'] = '检测站费用';
            UserBalanceService::instance()->operatorBalance($order['service_provider_uid'], 'system', $reviewPrice, $data);
        }

        $this->success('操作年审完成成功');
    }

    /**
     * 获取输入订单
     * @return array [map, order]
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    private function getOrderData(): array
    {
        $map = $this->_vali(['service_provider_uid.value' => $this->uuid, 'order_no.require' => '订单号不能为空']);
        $order = $this->app->db->name('car_order_review')->where($map)->find();

        if (empty($order)) {
            $this->error('读取订单失败');
        }

        return [$map, $order];
    }
}